//
//  ChartSocketController.m
//  Chart
//
//  Created by caojun on 14/12/1.
//
//

#import "ChartSocketController.h"
#import "ChartSocketDelegate.h"
#import "ChartSocketLogger.h"
#import "YSSecurities.h"
#import "CJQuoteList.h"
#import "YTXRequestConfig.h"

#import "ChartSocketController+Observe.h"
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <YTXCommonSocket/CommonSocket.h>
#import "EFSNFXGTradeSocketMessage.h"
//#import "QHQuoteManager.h"
#import "YSSecuritiesManager.h"
#import "EFSChartSocketManager.h"


@implementation CJTask

- (BOOL)isEqualWithTask:(CJTask *)task {
    return [task.key isEqualToString:self.key] &&
    [task.method isEqualToString:self.method] &&
    [task.parameter isEqualToString:task.parameter];
}

+ (instancetype)taskWithKey:(NSString *)key
                 withMethod:(NSString *)method
             withParameters:(NSString *)para {
    CJTask *task = [[CJTask alloc] init];
    task.key = key;
    task.method = method;
    task.parameter = para;
    return task;
}

@end


@interface ChartSocketController()

@property (nonatomic, assign) UInt16 seq;

@property (nonatomic) dispatch_queue_t queue;


@end

@implementation ChartSocketController

#pragma mark - life cycle

- (instancetype)init {
    if (self = [super init]) {
        
        [self addListener];
        
        _taskList = [[NSMutableArray alloc] init];
        
        _queue = dispatch_queue_create("com.ys.lg.tradeDay", DISPATCH_QUEUE_SERIAL);
        
        _seq = 100;
        
        @weakify(self);
        [[[RACObserve(self.socket, isConnected) distinctUntilChanged] ignore:nil] subscribeNext:^(NSNumber *x) {
            @strongify(self);
            if (x.integerValue == 0) {
                self.status = ChartSocketConnectionStatusDEFAULT;
            }else{
                self.status = ChartSocketConnectionStatusSOCKETCONNECTED;
            }
        }];
        
        
        [self.socket.responseReceivedSignal subscribeNext:^(CommonSocketData *x) {
            @strongify(self);
            [self receivedInfo:x];
        }];
    }
    return self;
}

- (void)receivedInfo:(CommonSocketData *) x {
    LGlog(@"__后台收到数据:%zd",x.wCmd);
//    LGlog(@"__后台收到数据:%zd %@",x.wCmd,x.info);
    NSDictionary *info = x.info;
    switch (x.wCmd) {
        case YSSocketCommandSubscribeQuote:
            
            break;
        case YSSocketCommandPushQuote:
            [self mergeQuote:info];
            break;
        case YSSocketCommandPushTrdDy:
            [self changeTrDay:info];
            break;
        default:
            break;
    }

}

- (void)mergeQuote:(NSDictionary *)info {
//    NSLog(@"订阅数据");
//    LGlog(@"订阅数据：%@",info);
    YSSecurities *item = [YSSecurities quoteWithDictionary:info];
    [self.quoteList mergeQuote:item];
}

- (BOOL)isChangeTrDay:(NSString *)trDay {
    return ((trDay && trDay.length >= 4) && (![trDay isEqualToString:[YSSecuritiesManager sharedManager].trdDay]));
}

- (void)changeTrDaySuccess:(NSString *)trDay {
    [[YSSecuritiesManager sharedManager] setTrdDay:trDay];
    [self.quoteList reloadDataWithDB];
}

- (void)changeTrDay:(NSDictionary *)info {
    NSString *trDay = info[@"TrdDy"];
    
    if([self isChangeTrDay:trDay]){
        
        dispatch_sync(_queue, ^{
            @weakify(self);
            [[[YSSecuritiesManager sharedManager] fetchSecurities] subscribeError:^(NSError *error) {
                
            } completed:^{
                @strongify(self);
//                [self changeTrDaySuccess:trDay];
            }];
        });
    }
}

- (CommonSocket *)socket {
    if (_socket == nil) {
        _socket = [[CommonSocket alloc] initWithSocketConfig:[EFSNFXGTradeSocketMessage new]];
    }
    return _socket;
}

- (void)connect {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSString *tradeSocketUrl = [[YSRequestConfig shared]
                                    urlStringFromName:@"quotesocket.server"];
        
        NSArray *urlArray = [tradeSocketUrl componentsSeparatedByString:@":"];
        NSString *hostName = urlArray[0];
        if (urlArray.count == 2) {
            NSNumber *portNumber =
            [NSNumber numberWithLongLong:[urlArray[1] longLongValue]];
            UInt16 port = [portNumber unsignedShortValue];
            NSLog(@"socket 连接地址: %@ 端口: %zd",hostName,port);
            [self.socket connectWithHost:hostName withPort:port];
        }
    });
}

//手动关闭socket连接
- (void)disconnect {
    [self.socket disconnect];
}

- (void)reconnect {
    [self disconnect];
    [self connect];
}

- (void)dealloc {
    
    [self removeObserver:self forKeyPath:@"status"];
}

/** 添加监听 */
- (void)addListener {
    
    [self addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionOld context:nil];
}


- (void)clearTaskList {
    NSMutableArray *discardedItems = [NSMutableArray array];
    for (CJTask *task in _taskList) {
        [discardedItems addObject:task];
    }
    [_taskList removeObjectsInArray:discardedItems];
}

- (void)destorySocket{
    NSLog(@"销毁Socket");
}

- (void)begin{
    NSLog(@"准备开始");
    self.status = ChartSocketConnectionStatusBEGIN;
}

- (void)ready {
    NSLog(@"准备ready");
    self.status = ChartSocketConnectionStatusREADY;
//    [[EFSChartSocketManager sharedChartSocketController] subscribeWithID:@"64"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    
    if ([keyPath isEqual:@"status"]) {
        switch (self.status) {
            case ChartSocketConnectionStatusDEFAULT:
                [self clearTaskList];
                [self destorySocket];
                [self begin];
                break;
            case ChartSocketConnectionStatusBEGIN:
                [self connect];
                break;
            case ChartSocketConnectionStatusSOCKETCONNECTED:
                [self ready];
                break;
            case ChartSocketConnectionStatusREADY:
                [self doTasks];
                break;
            default:
                
                break;
        }
    }
}

- (int)inTask:(CJTask *)task {
    for (CJTask *itemTask in _taskList) {
        if ([task isEqualWithTask:itemTask]) {
            return (int)[_taskList indexOfObject:itemTask];
        }
    }
    return -1;
}

- (BOOL)addTask:(CJTask *)task {
    if ([self inTask:task] == -1) {
        [_taskList addObject:task];
        return YES;
    }
    
    return NO;
}

- (BOOL)removeTask:(CJTask *)task {
    int index = [self inTask:task];
    
    if (index > -1) {
        [_taskList removeObjectAtIndex:index];
        return YES;
    }
    
    return NO;
}

- (void)doTasks {
    NSMutableArray *discardedItems = [NSMutableArray array];
    for (CJTask *itemTask in _taskList) {
        SEL sel = NSSelectorFromString(itemTask.method);
        ((void (*)(id, SEL, NSString *))[self methodForSelector:sel])(
                                                                      self, sel, itemTask.parameter);
        [discardedItems addObject:itemTask];
    }
    
    [_taskList removeObjectsInArray:discardedItems];
}

- (void)sendSubscribeMessageWithID:(NSString *)metalID {
    
    NSMutableDictionary *param = [@{@"SubAry":metalID} mutableCopy];
    [self.socket emitWithRequestCode:YSSocketCommandSubscribeQuote
                                 seq:self.seq
                                info:param];
    self.seq+=1;
    
}

- (void)sendUnsubscribeMessageWithID:(NSString *)metalID {
    NSMutableDictionary *param = [@{@"UnSubAry":metalID} mutableCopy];
    [self.socket emitWithRequestCode:YSSocketCommandSubscribeQuote
                                 seq:self.seq
                                info:param];
    self.seq+=1;
}

- (void)shouldWithKey:(NSString *)key
       withMethodName:(NSString *)name
       withParameters:(NSString *)para {
    
    SEL sel = NSSelectorFromString(name);
    
    if (![self respondsToSelector:sel]) {
        return;
    }
    
    CJTask *task = [CJTask taskWithKey:key
                            withMethod:name
                        withParameters:para];
    
    if (self.didReallyReady) {
        ((void (*)(id, SEL, NSString *))[self methodForSelector:sel])(self, sel,
                                                                      para);
        
    } else {
        [self addTask:task];
        
    }
}

-(BOOL)didReallyReady
{
    NSLog(@"__连接状态: %zd",self.status == ChartSocketConnectionStatusREADY && self.socket && self.socket.isConnected.boolValue);
    return self.status == ChartSocketConnectionStatusREADY && self.socket && self.socket.isConnected.boolValue;
}

- (void)subscribeWithID:(NSString *)metalID {
    [self unsubscribeWithID:metalID];
    [self shouldWithKey:[self createSubscribeKeyWithID:metalID]
         withMethodName:@"sendSubscribeMessageWithID:"
         withParameters:metalID
     ];
}

- (void)unsubscribeWithID:(NSString *)metalID {
    [self removeTask:[CJTask taskWithKey:[self createSubscribeKeyWithID:metalID]
                              withMethod:@"sendSubscribeMessageWithID:"
                          withParameters:metalID]];
    
    if (self.status == ChartSocketConnectionStatusREADY) {
        [self shouldWithKey:[self createUnsubscribeKeyWithID:metalID]
             withMethodName:@"sendUnsubscribeMessageWithID:"
             withParameters:metalID];
    }
}

- (NSString *)createSubscribeKeyWithID:(NSString *)metalID {
    return [NSString stringWithFormat:@"%@+%@", @"subscribe", metalID];
}

- (NSString *)createUnsubscribeKeyWithID:(NSString *)metalID {
    return [NSString stringWithFormat:@"%@+%@", @"unsubscribe", metalID];
}

- (CJQuoteList *)quoteList {
    if (!_quoteList) {
        _quoteList = [[CJQuoteList alloc] init];
    }
    return _quoteList;
}

- (NSArray *)optionalQuotes
{
    return [self optionalQuoteIds];
}

@end
